<template>
  <div class="ts-form-table">
    <el-table :data="data" ref="table" :key="toggleIndex" width="400" border stripe :max-height="height"
      :header-cell-style="{ color: '#000' }" @row-contextmenu="rightClick" @row-click="clickTableRow" :row-key="rowKey">
      <el-table-column type="index" width="50" fixed="left">
        <template #header>
          <el-button v-if="!disabled && !onlyDelete" type="primary" size="small" :icon="Plus" circle @click="rowAdd">
          </el-button>
        </template>
        <template #default="scope" v-if="!disabled">
          <div class="ts-form-table-handle">
            <span>{{ scope.$index + 1 }}</span>
            <el-button type="danger" size="small" :icon="Delete" plain circle @click="rowDel(scope.row, scope.$index)">
            </el-button>
          </div>
        </template>
      </el-table-column>
      <el-table-column v-if="edit" label="" width="58">
        <template #default="scope">
          <el-tag @click="rowEdit(scope.row)">
            <Edit style="width: 1em; height: 1em" />
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="" width="58" v-if="dragSort">
        <template #default>
          <el-tag class="move" style="cursor: move">
            <DCaret style="width: 1em; height: 1em" />
          </el-tag>
        </template>
      </el-table-column>
      <slot></slot>
      <slot name="tableContent"></slot>
      <template #empty>
        {{ placeholder }}
      </template>
      <template #append>
        <slot name="append"></slot>
      </template>
    </el-table>
    <transition name="el-zoom-in-top">
      <ul v-if="contextMenuVisible" :style="{ left: position.x + 'px', top: position.y + 'px' }" class="contextmenu"
        id="contextmenu">
        <li @click="copyRowPaste">复制该行并粘贴</li>
        <li v-if="copyExcel" class="pasteExcel" @click="dialogVisible = true">粘贴excel数据</li>
        <hr />
      </ul>
    </transition>
    <el-dialog v-model="dialogVisible" title="excel数据导入" width="80%">
      <el-input type="textarea" v-model="excelStrData" v-on:paste="pasteExcelData" :rows="10"></el-input>
      <template #footer>
        <el-button plain type="primary" @click="exportExcelData">导 入</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {
  ref,
  onMounted,
  defineModel,
  nextTick,
  watch,
  onBeforeUpdate,
} from "vue";
import { Plus, Delete, DCaret, Edit } from "@element-plus/icons-vue";
import Sortable from "sortablejs";
import { deepClone } from "@/utils/arr";
import { ElMessage } from "element-plus";
// const clipboardObj = navigator.clipboard;
const emit = defineEmits(["updateIndex", "delete", "deleteAddData"]);
const props = defineProps({
  modelValue: { type: Array, default: () => [] },
  addTemplate: { type: Object, default: () => { } },
  placeholder: { type: String, default: "暂无数据" },
  dragSort: { type: Boolean, default: false },
  disabled: { type: Boolean, default: false },
  onlyDelete: { type: Boolean, default: false },
  edit: { type: Boolean, default: false },
  height: { type: Number, default: 500 },
  copyExcel: { type: Boolean, default: false },
  excelMap: { type: Object, default: () => { } },
  rowKey: { type: String, default: '' }
});
const data = defineModel();
const toggleIndex = ref(0);
const table = ref(null);
const copyRow = ref();
const contextMenuVisible = ref(false);
const dialogVisible = ref(false);
const position = ref({
  y: 0,
  x: 0,
});
const excelStrData = ref()
const excelData = ref();
watch(contextMenuVisible, (newValue) => {
  var cm = function (e) {
    let sp = document.getElementById("contextmenu");
    if (sp && !sp.contains(e.target)) {
      contextMenuVisible.value = false;
    }
  };
  if (newValue) {
    document.body.addEventListener("click", (e) => cm(e));
  } else {
    document.body.removeEventListener("click", (e) => cm(e));
  }
});
onMounted(() => {
  contextMenuVisible.value = false;
  if (props.dragSort) {
    rowDrop();
  }
});
onBeforeUpdate(() => {
  contextMenuVisible.value = false;
});
const rowDrop = () => {
  const tbody = table.value.$el.querySelector(".el-table__body-wrapper tbody");
  Sortable.create(tbody, {
    handle: ".move",
    animation: 300,
    ghostClass: "ghost",
    onEnd({ newIndex, oldIndex }) {
      if (!props.rowKey) {
        const tableData = deepClone(data.value);
        const currRow = tableData.splice(oldIndex, 1)[0];
        tableData.splice(newIndex, 0, currRow);
        data.value = tableData
        toggleIndex.value += 1
      }
      emit("updateIndex");
      nextTick(() => {
        rowDrop();
      });
    },
  });
};
const rowAdd = () => {
  const temp = JSON.parse(JSON.stringify(props.addTemplate));
  temp.operationType = "add";
  temp.itemIndex = data.value.length + 1;
  data.value.push(temp);
};
const rowDel = (row, index) => {
  if (row.operationType !== "add") {
    row.operationType = "delete";
    row.index = index;
    emit("delete", row);
  } else {
    emit("deleteAddData", row);
  }
  data.value.splice(index, 1);
  emit("updateIndex");
};
const rowEdit = (item) => {
  if (item.operationType == "") {
    item.operationType = "update";
  }
};
const updateIndex = () => {
  data.value.forEach((ele, index) => {
    ele.itemIndex = index + 1;
  });
};
const rightClick = (row, column, e) => {
  copyRow.value = row;
  e.preventDefault();
  contextMenuVisible.value = true;
  position.value.x = e.clientX + 1;
  position.value.y = e.clientY + 1;

  //FIX 右键菜单边缘化位置处理
  nextTick(() => {
    let sp = document.getElementById("contextmenu");
    if (document.body.offsetWidth - e.clientX < sp.offsetWidth) {
      position.value.x = document.body.offsetWidth - sp.offsetWidth + 1;
      position.value.y = e.clientY + 1;
    }
  });
};

const copyRowPaste = () => {
  data.value.push(copyRow.value);
};
// const pasteExcelData = async () => {
//   try {
//     const text = await navigator.clipboard.readText();
//     console.log(text);
//   } catch (error) {console.log(error)}
// };
const pasteExcelData = (e) => {
  e.stopPropagation(); //阻止事件冒泡
  let arr = []
  var clipboardData = e.clipboardData || window.clipboardData; // IE
  if (!clipboardData) {
    //chrome
    clipboardData = e.originalEvent.clipboardData;
  }
  let source = clipboardData.getData("Text");
  let rows = source.split("\n");
  for (let i = 0; i < rows.length; i++) {
    if (rows[i] !== "") {
      // 如果某一行不是空，再按列拆分
      let columns = rows[i].split("\t"); // 已经按列划分
      columns[columns.length - 1] = columns[columns.length - 1].replace(/\r$/, '')
      // columns = columns.filter(item => item.length > 0);
      let num = 0
      let dataone = JSON.parse(JSON.stringify(props.excelMap)); // 声明一行数组
      for (var key in dataone) {
        dataone[key] = columns[num]
        num += 1
        if (num > columns.length - 1) {
          break
        }
      }
      arr.push(dataone);
    }
  }
  excelData.value = arr
};
const exportExcelData = () => {
  data.value = data.value.concat(excelData.value)
  dialogVisible.value = false
  excelStrData.value = ''
}
</script>

<style lang="less" scoped>
.ts-form-table {
  width: 100%;
}

.ts-form-table .ts-form-table-handle {
  text-align: center;
}

.ts-form-table .ts-form-table-handle span {
  display: inline-block;
}

.ts-form-table .ts-form-table-handle button {
  display: none;
}

.ts-form-table .hover-row .ts-form-table-handle span {
  display: none;
}

.ts-form-table .hover-row .ts-form-table-handle button {
  display: inline-block;
}

.contextmenu {
  position: fixed;
  width: 200px;
  margin: 0;
  border-radius: 0px;
  background: var(--el-bg-color-overlay);
  border: 1px solid var(--el-border-color-light);
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 9999;
  list-style-type: none;
  padding: 10px 0;
}

.contextmenu hr {
  margin: 5px 0;
  border: none;
  height: 1px;
  font-size: 0px;
  background-color: var(--el-border-color-light);
}

.contextmenu li {
  display: flex;
  align-items: center;
  margin: 0;
  cursor: pointer;
  line-height: 30px;
  padding: 0 17px;
  color: #606266;
}

.contextmenu li i {
  font-size: 14px;
  margin-right: 10px;
}

.contextmenu li:hover {
  background-color: #ecf5ff;
  color: #66b1ff;
}

.contextmenu li.disabled {
  cursor: not-allowed;
  color: #bbb;
  background: transparent;
}
</style>
